﻿
Imports System.Threading

Public Class tally(Of threadsafe As _boolean)
    Private Shared ts As _boolean = Nothing
    Private _step As Int64
    Private _count As Int64
    Private _lock As Object = Nothing

    Private Sub lock()
        If +ts Then
            Monitor.Enter(_lock)
        End If
    End Sub

    Private Sub release()
        If +ts Then
            Monitor.Exit(_lock)
        End If
    End Sub

    Public Property [step]() As Int64
        Get
            Return _step
        End Get
        Set(ByVal value As Int64)
            lock()
            _step = value
            release()
        End Set
    End Property

    Public Function count() As Int64
        Return _count
    End Function

    Public Function tick() As Boolean
        Dim rtn As Boolean = False
        lock()
        _count += 1
        If _count = maxInt64 Then
            _count = 0
        End If
        If _step <= 0 OrElse _count Mod _step = 0 Then
            rtn = True
        Else
            rtn = False
        End If
        release()

        Return rtn
    End Function

    Protected Sub initial()
        If +ts Then
            _lock = New Object()
        End If
    End Sub

    Public Sub New()
        initial()
    End Sub

    Public Sub New(ByVal [step] As Int64)
        initial()
        Me.[step] = [step]
    End Sub

    Shared Sub New()
        ts = alloc(Of threadsafe)()
    End Sub
End Class

Public Class tally
    Inherits tally(Of _true)

    Public Sub New()
        MyBase.New()
    End Sub

    Public Sub New(ByVal [step] As Int64)
        MyBase.New([step])
    End Sub
End Class